#include "inc.h"

#define	SUCCESS	1
#define	FAIL	-1


void	*ThrWork(void	*pArg)
{
    _THREAD_INFO    *pThr;
	int				nThr = *(int *) pArg, nRet = 0;
	int				nTmpSd=-1;
	int			nSeqId;
	char		szGlobalSerialNo[20];

	pThr = &THR(nThr);

	Log(LOG_D, "[%4d] Work Thread Started\n", nThr);

	while(1) {

        switch ( THR(nThr).nState ) {
		case	THREAD_IDLE:

			nTmpSd = ConnCapSync(nThr);
			THR(nThr).nSd 		= nTmpSd;

			Log(LOG_D, "[%4d] SimWork Thread Wake up !! (%d)\n", nThr, THR(nThr).nSd);

pthread_mutex_lock(&_mEstLock);
			nSeqId = _nSeqId++;
			if ( _nSeqId >= _gnToSn )	_nSeqId = _gnFromSn;
			THR(nThr).nSeqId = _nSeqId;
pthread_mutex_unlock(&_mEstLock);
			Log(LOG_D, "[%4d] SimWork Thread SeqId (%d)\n", nThr, nSeqId);

#if	0
			if ( Req2Svr_Retrieve(nThr) > 0 ) {
				MoveFsm(nThr, THREAD_BUSY);
			} else {
                Log(LOG_I, "[%4d] Send Retrieve Fail. (IDLE -> INIT)\n", nThr, szGlobalSerialNo);
                FreeTHR(nThr);
			}
#else
			MoveFsm(nThr, THREAD_BUSY);

			switch(SIM_SYSP.nNextJob)
			{
			case	MT_RETRIEVE_REQ:
				if ( Req2Svr_Retrieve(nThr) == FAIL ) FreeTHR(nThr);
			break;

			case	MT_APPROVAL_REQ:
                if ( Req2Svr_Approval(nThr) == FAIL ) FreeTHR(nThr);
			break;

			case	MT_APPROVAL_CANCEL_REQ:
                if ( Req2Svr_ApprovalCancel(nThr) == FAIL ) FreeTHR(nThr);
			break;

			case	MT_GIFT_APPROVAL_REQ:
                if ( Req2Svr_GiftApproval(nThr) == FAIL ) FreeTHR(nThr);
			break;

			case	MT_GIFT_APPROVAL_CANCEL_REQ:
                if ( Req2Svr_GiftApprovalCancel(nThr) == FAIL ) FreeTHR(nThr);
			break;

			case	MT_SELLCHARGE_REQ:
				switch(SIM_SYSP.nServiceCode)
				{
				case    SC_CHARGE_GIFT1:
				case    SC_CHARGE_GIFT2:
                	if ( Req2Svr_SellCharge(nThr) == FAIL ) break;
				break;

				default:
                	if ( Req2Svr_SellCharge(nThr) == FAIL ) break;
					break;
				}
			break;

			case	MT_SELLCHARGE_CANCEL_REQ:
			{
				switch(SIM_SYSP.nServiceCode)
				{
				case    SC_SELL_CANCEL_GIFT1:
				case    SC_SELL_CANCEL_GIFT2:
				case    SC_SELL_CANCEL_GIFT3:
                	if ( Req2Svr_SellChargeCancel(nThr) == FAIL ) FreeTHR(nThr);
				break;

				default:
                	if ( Req2Svr_SellChargeCancel(nThr) == FAIL ) FreeTHR(nThr);
				break;
			}
			break;

			default:
				Log(LOG_I, "[%4d] None NextJob\n", nThr);
				FreeTHR(nThr);
			break;

			}
		}
#endif
			break;

		case	THREAD_BUSY:
			Log(LOG_D, "[%4d] Thread Busy\n", nThr);

			if(THR(nThr).nSd <= 0) {
				Log(LOG_C, "[%4d] Something wrong\n", nThr);
                FreeTHR(nThr);
                break;
            }
			CapRun(nThr);
            FreeTHR(nThr);
			break;

		case	THREAD_INIT:
		default:
			 break;

		}
		Sleep_m(1000);
	}
	return ((void *)SUCCESS);
}

void FreeTHR(int nThr)
{
    Log(LOG_D, "[%4d] FreeTHR \n", nThr);

    if ( THR(nThr).nSd > 0 ) {
        if ( THR(nThr).nRdShut == 0 )   {
            Sleep_m(100);
            shutdown(THR(nThr).nSd, SHUT_RD);
            Log(LOG_D, "[%4d] shutdown SHUT_RD Close\n", nThr);
            THR(nThr).nRdShut = 1;
        }

        if ( THR(nThr).nWrShut == 0 )   {
            Sleep_m(100); //millisecond
            shutdown(THR(nThr).nSd, SHUT_WR);
            Log(LOG_D, "[%4d] shutdown SHUT_WR Close\n", nThr);
            THR(nThr).nWrShut = 1;
        }
        Sleep_m(500); //millisecond
        Log(LOG_D, "[%4d] close Sd(%d)\n", nThr, THR(nThr).nSd);
        close(THR(nThr).nSd);

        THR(nThr).nSd = -1;
    }

    THR(nThr).fp = NULL;

    THR(nThr).nWrShut = THR(nThr).nRdShut = 0;

    MoveFsm(nThr, THREAD_INIT);
}

int ConnCapSync(int nThr)
{
	int	nTmpSd = -1;

	while( nTmpSd <= 0 ) {
		nTmpSd = ClientOpen_Thr(SIM_SYSP.szCapIp, SIM_SYSP.szCapPort, (2*1000), 1, 256*1024);
		Log(LOG_I, "[%4d] connect try (%s)(%s)\n", nThr, SIM_SYSP.szCapIp, SIM_SYSP.szCapPort);
		if ( nTmpSd <= 0 ) Sleep_m(1000);
	}

	return nTmpSd;
}



#if	0
int GetIdleThread()
{
    int i;
    for(i=0; i<SIM_SYSP.nMaxCap; i++) {
        if ( THR(i).nSd < 0 ) return i;
    }
	Log(LOG_C, "%s%sCannot found idle thread%s\n", E_BOLD, T_RED, E_RELEASE);
    return -1;
}
#endif



int SendMsgToCap(int nThr, char *pData, int nLen)
{
	_MSG_HEAD_BGF *pstHead = (_MSG_HEAD_BGF *) pData;
    int     nLogLevelT, nRet = -1, nMsgType;
	int		nSd = THR(nThr).nSd;

	nMsgType = GetValueN(pstHead->messageType, sizeof(pstHead->messageType));
    
	DumpData(LOG_I, pData, nLen, (char *)"%s%s[%4d] (CAP) <- [%s] LEN[%d]%s\n", 
		E_BOLD, T_SKYBLUE, nThr, StrMsgType(nMsgType), nLen, E_RELEASE);

    nRet = WriteSocket_t(nSd, (char *)pData, nLen, 20*1000);
    
	if ( nRet <= 0 ) 
		Log(LOG_C, "[%4d] Send Error Msg Length (%d) nRet(%d)\n", nThr, nLen, nRet);
	else
		Log(LOG_I, "[%4d] Send Msg Length (%d) nRet(%d)\n", nThr, nLen, nRet);

    return nRet;    
}


int CapRun(int nThr)
{                   
    int             nRet;
    struct          timeval timeout;
    fd_set          fdIn;
    _TCP_R_MSG_MNG  stMng, *pstMng = &stMng;
    _BGF_MSG        stMsg, *pstMsg = &stMsg;
                    
    // Init TCP_MNG Structure
    memset( &stMng , 0x00, sizeof(_TCP_R_MSG_MNG));
    memset( pstMsg , 0x00, sizeof(_BGF_MSG));
    
    while(1) {

        timeout.tv_sec = 0;
        timeout.tv_usec = 50*1000;

        FD_ZERO(&fdIn);
    
        if ( THR(nThr).nSd > 0 )      FD_SET(THR(nThr).nSd,&fdIn);
        else    return SIM_FAIL;
    
        if( (nRet=select(THR(nThr).nSd+1,&fdIn,NULL,NULL,&timeout)) <= 0 ) {
            if(nRet < 0) {
                Log(LOG_C, "[%4d] select error (%s) Sd(%d)!!!!\n", nThr, strerror(errno), THR(nThr).nSd+1);
                return SIM_FAIL;
            }
            continue;
        }

        if (THR(nThr).nSd>0 && FD_ISSET(THR(nThr).nSd,&fdIn) ) {
            nRet = BgfReadTCP(nThr, THR(nThr).nSd, pstMng, pstMsg);

            switch(nRet) {
                case    0:  // more data
                    continue;
        
                case    1:  // tcp socket read succ
                    Log(LOG_I, "[%4d] DevMsgHdl: Sd(%d)\n", nThr, THR(nThr).nSd);
                    nRet = CapMsgHdl(nThr, THR(nThr).nSd, (char *)pstMsg);

                    memset(pstMng, 0x00, sizeof(_TCP_R_MSG_MNG));
                    memset(pstMsg , 0x00, BGF_BODY_SIZE);

                    if ( nRet == SUCC ) {
                        Log(LOG_I, "[%4d] CapMsgHdl SUCC Sd(%d)\n", nThr, THR(nThr).nSd);
                        return SUCC;
                    } else {
                        Log(LOG_I, "[%4d] CapMsgHdl FAIL Sd(%d)\n", nThr, THR(nThr).nSd);
                        return FAIL;
                    }
                    break;

                default:
                    Log(LOG_C, "[%4d] First Reset by peer Sd(%d) BgfReadTCP nRet(%d)\n", nThr, THR(nThr).nSd, nRet);
                    memset(pstMng, 0x00, sizeof(_TCP_R_MSG_MNG));
                    memset(pstMsg , 0x00, BGF_BODY_SIZE);
                    return FAIL;
            }
        }
    }
}


int CapMsgHdl(int nThr, int nSd, char *pData)
{
	_MSG_HEAD_BGF	*pstHead = (_MSG_HEAD_BGF *) pData;
    int        	nMsgType, nLen;
    int         nMsgId, nLogLevelT;

	nLen = GetValueN(pstHead->bodyLength, sizeof(pstHead->bodyLength)) + BGF_HEAD_SIZE;
	nMsgType = GetValueN(pstHead->messageType, sizeof(pstHead->messageType));

	Log(LOG_I, (char *)"[%4d] LEN(%d)\n", nThr, nLen);
	Log(LOG_I, (char *)"[%4d] MSGTYPE(%s)\n", nThr, StrMsgType(nMsgType));

	DumpData(LOG_I, pData, nLen, (char *)"%s%s[%4d] (CAP) -> [%s] LEN[%d]%s\n", 
			E_BOLD, T_YELLOW, nThr, StrMsgType(nMsgType), nLen, E_RELEASE);

    switch( nMsgType ) {
        case MT_RETRIEVE_RSP:
			SaveFile("Retrive-RSP", pData, nLen);
            if ( ProcRsp_Retrieve(nThr, pData) == FAIL )	FreeTHR(nThr);

			Log(LOG_I, "[%4d] NextJob (%s)\n", nThr, StrMsgType(nMsgType)); 
		break;
	
        case MT_APPROVAL_RSP:
			SaveFile("Approval-RSP", pData, nLen);
            ProcRsp_Approval(nThr, pData);
			FreeTHR(nThr);
            break;

        case MT_APPROVAL_CANCEL_RSP:
			SaveFile("ApprovalCancel-RSP", pData, nLen);
            ProcRsp_ApprovalCancel(nThr, pData);
			FreeTHR(nThr);

            break;

        case MT_GIFT_APPROVAL_RSP:
			SaveFile("GiftApproval-RSP", pData, nLen);
            ProcRsp_GiftApproval(nThr, pData);
			FreeTHR(nThr);
            break;

        case MT_GIFT_APPROVAL_CANCEL_RSP:
			SaveFile("GiftApprovalCancel-RSP", pData, nLen);
            ProcRsp_GiftApprovalCancel(nThr, pData);
			FreeTHR(nThr);

            break;

        case MT_SELLCHARGE_RSP:
			SaveFile("SellCharge-RSP", pData, nLen);
            ProcRsp_SellCharge(nThr, pData);
			FreeTHR(nThr);

            break;

        case MT_SELLCHARGE_CANCEL_RSP:
			SaveFile("SellChargeCancel-RSP", pData, nLen);
            Log(LOG_I, "[%4d] (CAP) -> ACK\n", nThr);
            ProcRsp_SellChargeCancel(nThr, pData);
			FreeTHR(nThr);
            break;

        default:
            Log(LOG_C, "[%4d] Unknow CAP Request\n", nThr);
            return SUCC;
        break;
    }
    return SUCC;
}

int Req2Svr_Retrieve(int nThr)
{
    int			nLen = 0;
	char		szMsg[MAX_MSG_SIZE_BGF], *pMsg = (char *)szMsg;
	char		szBody[BGF_BODY_SIZE], *pBody = (char *)szBody;
	char		szHead[BGF_HEAD_SIZE], *pHead = (char *)szHead;

    memset(pMsg, 0x00, MAX_MSG_SIZE_BGF);
    memset(pHead, 0x00, BGF_HEAD_SIZE);
    memset(pBody, 0x00, BGF_BODY_SIZE);

	Log(LOG_I, "[%4d] Req2Srv_Retrieve\n", nThr);

	switch(atoi(SIM_SYSP.stCmn.cardType)) {
		case	CT_GIFT_CARD:
			nLen = SetGiftRetrieveReq(nThr, pBody);
		break;

		default:
			nLen = SetRetrieveReq(nThr, pBody);
	}

    //nLen += SetHeader(nThr, pHead, nLen, MT_RETRIEVE_REQ, SC_RETRIEVE_GIFT, CT_CHANGE);
    nLen += SetHeader(nThr, pHead, nLen, MT_RETRIEVE_REQ, SC_RETRIEVE_OTHER, CT_CHANGE);

	memcpy(pMsg, pHead, BGF_HEAD_SIZE); 
	memcpy(pMsg+BGF_HEAD_SIZE, pBody, nLen-BGF_HEAD_SIZE); 

	Print_Header(nThr, (_MSG_HEAD_BGF *)pHead);
	Print_RetrieveReq(nThr, pBody);

	SaveFile("Retrive-REQ", pMsg, nLen);

	Log(LOG_I, "[%4d] Req2Srv_Retrieve total size (%d)\n", nThr, nLen);

    return  SendMsgToCap(nThr, (char *)pMsg, nLen);
}


int Req2Svr_Approval(int nThr)
{
    int			nLen = 0;
	char		szMsg[MAX_MSG_SIZE_BGF], *pMsg = (char *)szMsg;
	char		szBody[BGF_BODY_SIZE], *pBody = (char *)szBody;
	char		szHead[BGF_HEAD_SIZE], *pHead = (char *)szHead;

    memset(pMsg, 0x00, MAX_MSG_SIZE_BGF);
    memset(pHead, 0x00, BGF_HEAD_SIZE);
    memset(pBody, 0x00, BGF_BODY_SIZE);

	Log(LOG_I, "[%4d] Req2Srv_Approval\n", nThr);

	nLen = SetApprovalReq(nThr, pBody);
    nLen += SetHeader(nThr, pHead, nLen, MT_APPROVAL_REQ, SC_APPROVAL_GIFT, CT_CHANGE);

	memcpy(pMsg, pHead, BGF_HEAD_SIZE); 
	memcpy(pMsg+BGF_HEAD_SIZE, pBody, nLen-BGF_HEAD_SIZE); 

	SaveFile("Approval-REQ", pMsg, nLen);

    return  SendMsgToCap(nThr, (char *)pMsg, nLen);
}

int Req2Svr_ApprovalCancel(int nThr)
{
    int			nLen = 0;
	char		szMsg[MAX_MSG_SIZE_BGF], *pMsg = (char *)szMsg;
	char		szBody[BGF_BODY_SIZE], *pBody = (char *)szBody;
	char		szHead[BGF_HEAD_SIZE], *pHead = (char *)szHead;

    memset(pMsg, 0x00, MAX_MSG_SIZE_BGF);
    memset(pHead, 0x00, BGF_HEAD_SIZE);
    memset(pBody, 0x00, BGF_BODY_SIZE);

	Log(LOG_I, "[%4d] Req2Srv_ApprovalCancel\n", nThr);

	nLen = SetApprovalCancelReq(nThr, pBody);
    nLen += SetHeader(nThr, pHead, nLen, MT_APPROVAL_CANCEL_REQ, SC_APPROVAL_CANCEL_GIFT1, CT_CHANGE);

	memcpy(pMsg, pHead, BGF_HEAD_SIZE); 
	memcpy(pMsg+BGF_HEAD_SIZE, pBody, nLen-BGF_HEAD_SIZE); 

	SaveFile("ApprovalCancel-REQ", pMsg, nLen);

    return  SendMsgToCap(nThr, (char *)pMsg, nLen);
}

int Req2Svr_GiftApproval(int nThr)
{
    int			nLen = 0;
	char		szMsg[MAX_MSG_SIZE_BGF], *pMsg = (char *)szMsg;
	char		szBody[BGF_BODY_SIZE], *pBody = (char *)szBody;
	char		szHead[BGF_HEAD_SIZE], *pHead = (char *)szHead;

    memset(pMsg, 0x00, MAX_MSG_SIZE_BGF);
    memset(pHead, 0x00, BGF_HEAD_SIZE);
    memset(pBody, 0x00, BGF_BODY_SIZE);

	Log(LOG_I, "[%4d] Req2Srv_GiftApproval\n", nThr);

	nLen = SetGiftApprovalReq(nThr, pBody);
    nLen += SetHeader(nThr, pHead, nLen, MT_GIFT_APPROVAL_REQ, SC_APPROVAL_GIFT, CT_CHANGE);

	memcpy(pMsg, pHead, BGF_HEAD_SIZE); 
	memcpy(pMsg+BGF_HEAD_SIZE, pBody, nLen-BGF_HEAD_SIZE); 

	SaveFile("GiftApproval-REQ", pMsg, nLen);

    return  SendMsgToCap(nThr, (char *)pMsg, nLen);
}

int Req2Svr_GiftApprovalCancel(int nThr)
{
    int			nLen = 0;
	char		szMsg[MAX_MSG_SIZE_BGF], *pMsg = (char *)szMsg;
	char		szBody[BGF_BODY_SIZE], *pBody = (char *)szBody;
	char		szHead[BGF_HEAD_SIZE], *pHead = (char *)szHead;

    memset(pMsg, 0x00, MAX_MSG_SIZE_BGF);
    memset(pHead, 0x00, BGF_HEAD_SIZE);
    memset(pBody, 0x00, BGF_BODY_SIZE);

	Log(LOG_I, "[%4d] Req2Srv_GiftApprovalCancel\n", nThr);

	nLen = SetGiftApprovalCancelReq(nThr, pBody);
    nLen += SetHeader(nThr, pHead, nLen, MT_GIFT_APPROVAL_CANCEL_REQ, SC_APPROVAL_CANCEL_GIFT1, CT_CHANGE);

	memcpy(pMsg, pHead, BGF_HEAD_SIZE); 
	memcpy(pMsg+BGF_HEAD_SIZE, pBody, nLen-BGF_HEAD_SIZE); 

	SaveFile("GiftApprovalCancel-REQ", pMsg, nLen);

    return  SendMsgToCap(nThr, (char *)pMsg, nLen);
}

int Req2Svr_SellCharge(int nThr)
{
    int			nLen = 0;
	char		szMsg[MAX_MSG_SIZE_BGF], *pMsg = (char *)szMsg;
	char		szBody[BGF_BODY_SIZE], *pBody = (char *)szBody;
	char		szHead[BGF_HEAD_SIZE], *pHead = (char *)szHead;

    memset(pMsg, 0x00, MAX_MSG_SIZE_BGF);
    memset(pHead, 0x00, BGF_HEAD_SIZE);
    memset(pBody, 0x00, BGF_BODY_SIZE);

	Log(LOG_I, "[%4d] Req2Srv_SellChage\n", nThr);

	nLen = SetSellChargeReq(nThr, pBody);
    nLen += SetHeader(nThr, pHead, nLen, MT_SELLCHARGE_REQ, SIM_SYSP.nServiceCode, CT_CASH);

	memcpy(pMsg, pHead, BGF_HEAD_SIZE); 
	memcpy(pMsg+BGF_HEAD_SIZE, pBody, nLen-BGF_HEAD_SIZE); 

	SaveFile("SellCharge-REQ", pMsg, nLen);

    return	SendMsgToCap(nThr, (char *)pMsg, nLen);
}

int Req2Svr_SellChargeCancel(int nThr)
{
    int			nLen = 0;
	char		szMsg[MAX_MSG_SIZE_BGF], *pMsg = (char *)szMsg;
	char		szBody[BGF_BODY_SIZE], *pBody = (char *)szBody;
	char		szHead[BGF_HEAD_SIZE], *pHead = (char *)szHead;

    memset(pMsg, 0x00, MAX_MSG_SIZE_BGF);
    memset(pHead, 0x00, BGF_HEAD_SIZE);
    memset(pBody, 0x00, BGF_BODY_SIZE);

	Log(LOG_I, "[%4d] Req2Srv_SellChargeCancel\n", nThr);

	nLen = SetSellChargeCancelReq(nThr, pBody);
    nLen += SetHeader(nThr, pHead, nLen, MT_SELLCHARGE_CANCEL_REQ, SIM_SYSP.nServiceCode, CT_CASH);

	memcpy(pMsg, pHead, BGF_HEAD_SIZE); 
	memcpy(pMsg+BGF_HEAD_SIZE, pBody, nLen-BGF_HEAD_SIZE); 

	SaveFile("SellChargeCancel-REQ", pMsg, nLen);

    return  SendMsgToCap(nThr, (char *)pMsg, nLen);
}


int ProcRsp_Retrieve(int nThr, char *pData)
{
    return	SUCC;
}

int ProcRsp_Approval(int nThr, char *pData)
{
    return	SUCC;
}

int ProcRsp_ApprovalCancel(int nThr, char *pData)
{
    return	SUCC;
}

int ProcRsp_GiftApproval(int nThr, char *pData)
{
    return	SUCC;
}

int ProcRsp_GiftApprovalCancel(int nThr, char *pData)
{
    return	SUCC;
}

int ProcRsp_SellCharge(int nThr, char *pData)
{
    return	SUCC;
}

int ProcRsp_SellChargeCancel(int nThr, char *pData)
{
    return	SUCC;
}


void MoveFsm(int nThr, int nState)
{
pthread_mutex_lock(&THR(nThr).lock);
	THR(nThr).nState 	= nState;
pthread_mutex_unlock(&THR(nThr).lock);
}

int	SetHeader(int nThr, char *pMsg, int nBodyLength, int nMsgType, int nServiceCode, int nReqMethod)
{
	_MSG_HEAD_BGF	*pstHead = (_MSG_HEAD_BGF *) pMsg;
    int nBodyLen = 0, nEnco = 0, nLen = 0;
	char	szOut[128], szCardId[16];

	time_t  tCur    = time(NULL);
	struct  tm *Tm;
	char	szDateTime[20];
		
	memset(szDateTime, 0x00, sizeof(szDateTime));
	Tm = localtime(&tCur);
	sprintf(szDateTime,"%.4d%.2d%.2d%.2d%.2d%.2d", 
			Tm->tm_year +1900,Tm->tm_mon+1,Tm->tm_mday,Tm->tm_hour, Tm->tm_min,Tm->tm_sec);

	memset(pstHead, 0x00, BGF_HEAD_SIZE);

    SetValueN0(pstHead->version, 1, sizeof(pstHead->version));
    SetValueN0(pstHead->messageType, nMsgType, sizeof(pstHead->messageType));
    SetValueN0(pstHead->serviceCode, nServiceCode, sizeof(pstHead->serviceCode));
    SetValue(pstHead->cooperationCompanyCode, "60", sizeof(pstHead->cooperationCompanyCode));
    SetValue(pstHead->ApprovalDateTime, szDateTime, sizeof(pstHead->ApprovalDateTime));
    SetValue(pstHead->merchantBranchCode, MSG.merchantBranchCode, sizeof(pstHead->merchantBranchCode));
    SetValue(pstHead->hangCode, MSG.hangCode, sizeof(pstHead->hangCode));
    SetValue(pstHead->deviceType, MSG.deviceType, sizeof(pstHead->deviceType));
    SetValue(pstHead->deviceId, "92000401", sizeof(pstHead->deviceId));
    SetValue(pstHead->cardType, MSG.cardType, sizeof(pstHead->cardType));

	if ( _gnPerf_f == ON ) {
		if ( atoi(MSG.cardType) != 4 && nMsgType != MT_SELLCHARGE_REQ )
		{
			sprintf(szCardId, "%.16d", THR(nThr).nSeqId);
			SetValue(pstHead->cardId, szCardId, sizeof(pstHead->cardId));
		}
	}else{
		if ( atoi(MSG.cardType) != 4 && nMsgType != MT_SELLCHARGE_REQ )
			SetValue(pstHead->cardId, MSG.cardId, sizeof(pstHead->cardId));
	}

    SetValueN(pstHead->requestMethodCode, nReqMethod, sizeof(pstHead->requestMethodCode));
    SetValueN(pstHead->bodyLength, nBodyLength, sizeof(pstHead->bodyLength));

	GetValue(pstHead->bodyLength, szOut, sizeof(pstHead->bodyLength));
	Log(LOG_I, "[%4d] nBodyLength (%d)(%s)\n", nThr, nBodyLength, szOut);

	return	BGF_HEAD_SIZE;
}

int	SetRetrieveReq(int nThr, char *pReq)
{
	_BGF_RETRIEVE_REQ	stReq, *pstReq = &stReq;
	int		nEnco = 0, nLen = 0;
	int		nProductCount, i;
	char	szOut[128], szGlobalSerialNo[128];

    Log(LOG_I, "[%4d] Begin Encode Retrieve --------------------------\n", nThr);

	nEnco += SetValue(pReq+nEnco, MSG.globalSerialNo, sizeof(pstReq->globalSerialNo));
	nEnco += SetValue(pReq+nEnco, MSG.price, sizeof(pstReq->price));
	nEnco += SetValue(pReq+nEnco, MSG.productCount, sizeof(pstReq->productCount));

    nProductCount = atoi(MSG.productCount);
    Log(LOG_I, "[%4d] productCount(%d)\n", nThr, nProductCount);

	for(i=0; i<nProductCount; i++)
	{
		nEnco += SetValue(pReq+nEnco, MSG.stPlu[i].productId, sizeof(pstReq->stPlu[i].productId));
		nEnco += SetValue(pReq+nEnco, MSG.stPlu[i].productBarcode, sizeof(pstReq->stPlu[i].productBarcode));
		nEnco += SetValue(pReq+nEnco, MSG.stPlu[i].productNumber, sizeof(pstReq->stPlu[i].productNumber));
		nEnco += SetValue(pReq+nEnco, MSG.stPlu[i].productProviderCode, sizeof(pstReq->stPlu[i].productProviderCode));
		nEnco += SetValue(pReq+nEnco, MSG.stPlu[i].productCost, sizeof(pstReq->stPlu[i].productCost));
		nEnco += SetValue(pReq+nEnco, MSG.stPlu[i].productCoPrice, sizeof(pstReq->stPlu[i].productCoPrice));
		nEnco += SetValue(pReq+nEnco, MSG.stPlu[i].productMaPrice, sizeof(pstReq->stPlu[i].productMaPrice));
	}


    Log(LOG_I, "[%4d] End Encode Retrieve BodyLen(%d)--------------------------\n", nThr, nEnco);

	return nEnco;
}

/**
 *	@brief This is a function of decoding Message Type paramenter
 *	@param pData :  
 *	@return char *
 *	@remark
 */
int	SetApprovalReq(int nThr, char *pReq)
{
	_BGF_APPROVAL_REQ	*pstReq = (_BGF_APPROVAL_REQ *)pReq;
	int		nBodyLen = 0, nEnco = 0, nLen = 0;
	int		nProductCount, i;
	char	szOut[128], szGlobalSerialNo[128];

    Log(LOG_I, "[%4d] Begin Encode Approval --------------------------\n", nThr);

	nEnco += SetValue(pReq+nEnco, MSG.globalSerialNo, sizeof(pstReq->globalSerialNo));
	nEnco += SetValue(pReq+nEnco, MSG.saleCode, sizeof(pstReq->saleCode));
	nEnco += SetValue(pReq+nEnco, MSG.productCount, sizeof(pstReq->productCount));

    nProductCount = atoi(MSG.productCount);
    Log(LOG_I, "[%4d] productCount(%d)\n", nThr, nProductCount);

	for(i=0; i<nProductCount; i++)
	{
		nEnco += SetValue(pReq+nEnco, MSG.stPlu[i].productId, sizeof(pstReq->stPlu[i].productId));
		nEnco += SetValue(pReq+nEnco, MSG.stPlu[i].productBarcode, sizeof(pstReq->stPlu[i].productBarcode));
		nEnco += SetValue(pReq+nEnco, MSG.stPlu[i].productNumber, sizeof(pstReq->stPlu[i].productNumber));
/*
		nEnco += SetValue(pReq+nEnco, MSG.stPlu[i].productProviderCode, sizeof(pstReq->stPlu[i].productProviderCode));
		nEnco += SetValue(pReq+nEnco, MSG.stPlu[i].productCost, sizeof(pstReq->stPlu[i].productCost));
		nEnco += SetValue(pReq+nEnco, MSG.stPlu[i].productCoPrice, sizeof(pstReq->stPlu[i].productCoPrice));
		nEnco += SetValue(pReq+nEnco, MSG.stPlu[i].productMaPrice, sizeof(pstReq->stPlu[i].productMaPrice));
*/
		nEnco += SetValue(pReq+nEnco, " ", sizeof(pstReq->stPlu[i].productProviderCode));
		nEnco += SetValue(pReq+nEnco, " ", sizeof(pstReq->stPlu[i].productCost));
		nEnco += SetValue(pReq+nEnco, " ", sizeof(pstReq->stPlu[i].productCoPrice));
		nEnco += SetValue(pReq+nEnco, " ", sizeof(pstReq->stPlu[i].productMaPrice));
	}
/*
	nEnco += SetValue(pReq+nEnco, "12345", sizeof(pstReq->trackII));
	nEnco += SetValue(pReq+nEnco, MSG.giftCardKind, sizeof(pstReq->giftCardKind));
	nEnco += SetValue(pReq+nEnco, MSG.exchangeCode, sizeof(pstReq->exchangeCode));
	nEnco += SetValue(pReq+nEnco, MSG.giftKindCode, sizeof(pstReq->giftKindCode));
	nEnco += SetValue(pReq+nEnco, MSG.settlementAmount, sizeof(pstReq->settlementAmount));
	nEnco += SetValue(pReq+nEnco, MSG.passWord, sizeof(pstReq->passWord));
	nEnco += SetValue(pReq+nEnco, MSG.cashierId, sizeof(pstReq->cashierId));
	nEnco += SetValue(pReq+nEnco, MSG.billNo, sizeof(pstReq->billNo));
*/
	nEnco += SetValue(pReq+nEnco, " ", sizeof(pstReq->trackII));
	nEnco += SetValue(pReq+nEnco, MSG.giftCardKind, sizeof(pstReq->giftCardKind));
	nEnco += SetValue(pReq+nEnco, MSG.exchangeCode, sizeof(pstReq->exchangeCode));
	nEnco += SetValue(pReq+nEnco, MSG.giftKindCode, sizeof(pstReq->giftKindCode));

	if( (strncmp(MSG.cardType, "0", 1) == 0) || (strncmp(MSG.cardType, "4", 1) == 0) ){
		nEnco += SetValue(pReq+nEnco, MSG.settlementAmount, sizeof(pstReq->settlementAmount));
	} else {
		nEnco += SetValue(pReq+nEnco, "     ", sizeof(pstReq->settlementAmount));
	}

	nEnco += SetValue(pReq+nEnco, " ", sizeof(pstReq->passWord));
	nEnco += SetValue(pReq+nEnco, " ", sizeof(pstReq->cashierId));
	nEnco += SetValue(pReq+nEnco, MSG.billNo, sizeof(pstReq->billNo));
    Log(LOG_I, "[%4d] End Encode Approval BodyLen(%d) --------------------------\n", nThr, nEnco);

	return nEnco;
}

/**
 *	@brief This is a function of decoding Message Type paramenter
 *	@param pData :  
 *	@return char *
 *	@remark
 */
int	SetApprovalCancelReq(int nThr, char *pReq)
{
	_BGF_APPROVAL_CANCEL_REQ	*pstReq = (_BGF_APPROVAL_CANCEL_REQ *)pReq;

	int		nBodyLen = 0, nEnco = 0, nLen = 0;
	int		nProductCount, i;
	char	szOut[128], szGlobalSerialNo[128];

    Log(LOG_I, "[%4d] Begin Encode ApprovalCancel --------------------------\n", nThr);

	nEnco += SetValue(pReq+nEnco, MSG.globalSerialNo, sizeof(pstReq->globalSerialNo));
	nEnco += SetValue(pReq+nEnco, MSG.originalApprovalDate, sizeof(pstReq->originalApprovalDate));
    nEnco += SetValue(pReq+nEnco, MSG.originalApprovalAmount, sizeof(pstReq->originalSettlementAmount));
    nEnco += SetValue(pReq+nEnco, MSG.originalApprovalNo, sizeof(pstReq->originalApprovalNo));
    nEnco += SetValue(pReq+nEnco, MSG.originalSaleCode, sizeof(pstReq->originalSaleCode));
	nEnco += SetValue(pReq+nEnco, MSG.productCount, sizeof(pstReq->productCount));

    nProductCount = atoi(MSG.productCount);

    Log(LOG_I, "[%4d] globalSerialNo(%s)\n", nThr, szGlobalSerialNo);
    Log(LOG_I, "[%4d] productCount(%d)\n", nThr, nProductCount);

	for(i=0; i<nProductCount; i++)
	{
		nEnco += SetValue(pReq+nEnco, MSG.stPlu[i].productId, sizeof(pstReq->stPlu[i].productId));
		nEnco += SetValue(pReq+nEnco, MSG.stPlu[i].productBarcode, sizeof(pstReq->stPlu[i].productBarcode));
		nEnco += SetValue(pReq+nEnco, MSG.stPlu[i].productNumber, sizeof(pstReq->stPlu[i].productNumber));
		nEnco += SetValue(pReq+nEnco, MSG.stPlu[i].productProviderCode, sizeof(pstReq->stPlu[i].productProviderCode));
		nEnco += SetValue(pReq+nEnco, MSG.stPlu[i].productCost, sizeof(pstReq->stPlu[i].productCost));
		nEnco += SetValue(pReq+nEnco, MSG.stPlu[i].productCoPrice, sizeof(pstReq->stPlu[i].productCoPrice));
		nEnco += SetValue(pReq+nEnco, MSG.stPlu[i].productMaPrice, sizeof(pstReq->stPlu[i].productMaPrice));
	}

	nEnco += SetValue(pReq+nEnco, "12345", sizeof(pstReq->trackII));
	nEnco += SetValue(pReq+nEnco, MSG.exchangeCode, sizeof(pstReq->exchangeCode));
	nEnco += SetValue(pReq+nEnco, MSG.giftKindCode, sizeof(pstReq->giftKindCode));
	nEnco += SetValue(pReq+nEnco, MSG.passWord, sizeof(pstReq->passWord));
	nEnco += SetValue(pReq+nEnco, MSG.cashierId, sizeof(pstReq->cashierId));
	nEnco += SetValue(pReq+nEnco, MSG.billNo, sizeof(pstReq->billNo));
	nEnco += SetValue(pReq+nEnco, "12345", sizeof(pstReq->originalPosSerialId));
	nEnco += SetValue(pReq+nEnco, "1234", sizeof(pstReq->originalBillNo));

    Log(LOG_I, "[%4d] Begin Encode ApprovalCancel BodyLen(%d) --------------------------\n", nThr, nEnco);

	return nEnco;
}

/**
 *	@brief This is a function of decoding Message Type paramenter
 *	@param pData :  
 *	@return char *
 *	@remark
 */
int	SetGiftRetrieveReq(int nThr, char *pReq)
{
	_BGF_SELLorCHARGE_REQ	*pstReq = (_BGF_SELLorCHARGE_REQ	*) pReq;
	int		nEnco = 0;
	char	szOut[128], szGlobalSerialNo[128];
	//char	szBarCode[40];

	//memset(szBarCode, 0x00, sizeof(MSG.barCode));
	//sprintf(szBarCode, "40%s", MSG.barCode);

    Log(LOG_I, "[%4d] Begin Encode SellCharge --------------------------\n", nThr);

	nEnco += SetValue(pReq+nEnco, MSG.globalSerialNo, sizeof(pstReq->globalSerialNo));
	nEnco += SetValue(pReq+nEnco, " ", sizeof(pstReq->barCode));
	nEnco += SetValue(pReq+nEnco, MSG.giftCardKind, sizeof(pstReq->giftCardKind));
	nEnco += SetValue(pReq+nEnco, MSG.exchangeCode, sizeof(pstReq->exchangeCode));
	//nEnco += SetValue(pReq+nEnco, "60", sizeof(pstReq->cooperationCompanyCode)); //Field Delete
	nEnco += SetValue(pReq+nEnco, MSG.giftKindCode, sizeof(pstReq->giftKindCode));
	nEnco += SetValue(pReq+nEnco, MSG.cashierId, sizeof(pstReq->cashierId));
	nEnco += SetValue(pReq+nEnco, MSG.billNo, sizeof(pstReq->billNo));
	nEnco += SetValue(pReq+nEnco, MSG.saleCode, sizeof(pstReq->saleCode));
	nEnco += SetValue(pReq+nEnco, MSG.settlementAmount, sizeof(pstReq->settlementAmount));
	nEnco += SetValue(pReq+nEnco, MSG.barCode, sizeof(pstReq->trackII));

    Log(LOG_I, "[%4d] globalSerialNo(%s)\n", nThr, szGlobalSerialNo); 

    Log(LOG_I, "[%4d] End Encode SellCharge BodyLen(%d) --------------------------\n", nThr, nEnco);

	return nEnco;
}

/**
 *	@brief This is a function of decoding Message Type paramenter
 *	@param pData :  
 *	@return char *
 *	@remark
 */
int	SetGiftApprovalReq(int nThr, char *pReq)
{
	_BGF_GIFT_APPROVAL_REQ	*pstReq = (_BGF_GIFT_APPROVAL_REQ *)pReq;
	int		nBodyLen = 0, nEnco = 0, nLen = 0;
	int		nProductCount, i;
	char	szOut[128], szGlobalSerialNo[128];
	char	szCardNum[40];
	char	szCardId[16];
	
	memset(szCardId, 0x00, sizeof(szCardId));
	memset(szCardNum, 0x00, sizeof(szCardNum));
	strncpy(szCardId, MSG.cardId, sizeof(MSG.cardId));
	sprintf(szCardNum,"21%s=1811", szCardId);
	//sprintf(szCardNum,"21%s=1811", MSG.cardId);
    Log(LOG_C, "[%4d] Begin Encode GiftApproval --------------------------[%s]\n", nThr,MSG.cardId);

	nEnco += SetValue(pReq+nEnco, MSG.globalSerialNo, sizeof(pstReq->globalSerialNo));
	nEnco += SetValue(pReq+nEnco, MSG.barcode, sizeof(pstReq->barcode));
	nEnco += SetValue(pReq+nEnco, MSG.giftCardKind, sizeof(pstReq->card_gb));
	nEnco += SetValue(pReq+nEnco, MSG.exchangeCode, sizeof(pstReq->use_gb));
	nEnco += SetValue(pReq+nEnco, "60", sizeof(pstReq->comp_cd));
	nEnco += SetValue(pReq+nEnco, MSG.giftKindCode, sizeof(pstReq->kind_cd));
	nEnco += SetValue(pReq+nEnco, "20131105", sizeof(pstReq->req_ymd));
	nEnco += SetValue(pReq+nEnco, "121314", sizeof(pstReq->tran_no));
	nEnco += SetValue(pReq+nEnco, MSG.settlementAmount, sizeof(pstReq->amt));
	nEnco += SetValue(pReq+nEnco, MSG.saleCode, sizeof(pstReq->pay_gb));
	nEnco += SetValue(pReq+nEnco, "20131105", sizeof(pstReq->odeal_ymd));
	nEnco += SetValue(pReq+nEnco, MSG.originalApprovalNo, sizeof(pstReq->odeal_agreeno));
	nEnco += SetValue(pReq+nEnco, " ", sizeof(pstReq->odeal_id));
	nEnco += SetValue(pReq+nEnco, szCardNum, sizeof(pstReq->card_dat));
	nEnco += SetValue(pReq+nEnco, " ", sizeof(pstReq->odeal_card_agreeno));
    Log(LOG_I, "[%4d] End Encode GiftApproval BodyLen(%d) --------------------------\n", nThr, nEnco);

	return nEnco;
}

/**
 *	@brief This is a function of decoding Message Type paramenter
 *	@param pData :  
 *	@return char *
 *	@remark
 */
int	SetGiftApprovalCancelReq(int nThr, char *pReq)
{
	_BGF_GIFT_APPROVAL_CANCEL_REQ	*pstReq = (_BGF_GIFT_APPROVAL_CANCEL_REQ *)pReq;

	int		nBodyLen = 0, nEnco = 0, nLen = 0;
	int		nProductCount, i;
	char	szOut[128], szGlobalSerialNo[128];
	char	szCardNum[40];
	char	szCardId[16];
	
	memset(szCardId, 0x00, sizeof(szCardId));
	memset(szCardNum, 0x00, sizeof(szCardNum));
	strncpy(szCardId, MSG.cardId, sizeof(MSG.cardId));
	sprintf(szCardNum,"21%s=1811", szCardId);

    Log(LOG_I, "[%4d] Begin Encode GiftApprovalCancel --------------------------\n", nThr);

	nEnco += SetValue(pReq+nEnco, MSG.globalSerialNo, sizeof(pstReq->globalSerialNo));
	//nEnco += SetValue(pReq+nEnco, MSG.barcode, sizeof(pstReq->barcode));
	nEnco += SetValue(pReq+nEnco, " ", sizeof(pstReq->barcode));
	nEnco += SetValue(pReq+nEnco, MSG.giftCardKind, sizeof(pstReq->card_gb));
	nEnco += SetValue(pReq+nEnco, MSG.exchangeCode, sizeof(pstReq->use_gb));
	nEnco += SetValue(pReq+nEnco, "60", sizeof(pstReq->comp_cd));
	nEnco += SetValue(pReq+nEnco, MSG.giftKindCode, sizeof(pstReq->kind_cd));
	nEnco += SetValue(pReq+nEnco, "20131105", sizeof(pstReq->req_ymd));
	nEnco += SetValue(pReq+nEnco, "121314", sizeof(pstReq->tran_no));
	nEnco += SetValue(pReq+nEnco, MSG.settlementAmount, sizeof(pstReq->amt));
	nEnco += SetValue(pReq+nEnco, MSG.saleCode, sizeof(pstReq->pay_gb));
	nEnco += SetValue(pReq+nEnco, "20131105", sizeof(pstReq->odeal_ymd));
	nEnco += SetValue(pReq+nEnco, " ", sizeof(pstReq->odeal_agreeno));
	nEnco += SetValue(pReq+nEnco, " ", sizeof(pstReq->odeal_id));
	nEnco += SetValue(pReq+nEnco, szCardNum, sizeof(pstReq->card_dat));
	nEnco += SetValue(pReq+nEnco, MSG.originalApprovalNo, sizeof(pstReq->odeal_card_agreeno));

    Log(LOG_I, "[%4d] Begin Encode GiftApprovalCancel BodyLen(%d) --------------------------\n", nThr, nEnco);

	return nEnco;
}

/**
 *	@brief This is a function of decoding Message Type paramenter
 *	@param pData :  
 *	@return char *
 *	@remark
 */
int	SetSellChargeReq(int nThr, char *pReq)
{
	_BGF_SELLorCHARGE_REQ	*pstReq = (_BGF_SELLorCHARGE_REQ	*) pReq;
	int		nEnco = 0;
	char	szOut[128], szGlobalSerialNo[128];
	//char	szBarCode[40];

	//memset(szBarCode, 0x00, sizeof(MSG.barCode));
	//sprintf(szBarCode, "40%s", MSG.barCode);

    Log(LOG_I, "[%4d] Begin Encode SellCharge --------------------------\n", nThr);

	nEnco += SetValue(pReq+nEnco, MSG.globalSerialNo, sizeof(pstReq->globalSerialNo));
	nEnco += SetValue(pReq+nEnco, MSG.barCode, sizeof(pstReq->barCode));
	nEnco += SetValue(pReq+nEnco, MSG.giftCardKind, sizeof(pstReq->giftCardKind));
	nEnco += SetValue(pReq+nEnco, MSG.exchangeCode, sizeof(pstReq->exchangeCode));
	//nEnco += SetValue(pReq+nEnco, "60", sizeof(pstReq->cooperationCompanyCode));
	nEnco += SetValue(pReq+nEnco, MSG.giftKindCode, sizeof(pstReq->giftKindCode));
	nEnco += SetValue(pReq+nEnco, MSG.cashierId, sizeof(pstReq->cashierId));
	nEnco += SetValue(pReq+nEnco, MSG.billNo, sizeof(pstReq->billNo));
	nEnco += SetValue(pReq+nEnco, MSG.saleCode, sizeof(pstReq->saleCode));
	nEnco += SetValue(pReq+nEnco, MSG.settlementAmount, sizeof(pstReq->settlementAmount));
	nEnco += SetValue(pReq+nEnco, "12345", sizeof(pstReq->trackII));

    Log(LOG_I, "[%4d] globalSerialNo(%s)\n", nThr, szGlobalSerialNo); 

    Log(LOG_I, "[%4d] End Encode SellCharge BodyLen(%d) --------------------------\n", nThr, nEnco);

	return nEnco;
}

/**
 *	@brief This is a function of decoding Message Type paramenter
 *	@param pData :  
 *	@return char *
 *	@remark
 */
int	SetSellChargeCancelReq(int nThr, char *pReq)
{
	_BGF_SELLorCHARGE_CANCEL_REQ	*pstReq = (_BGF_SELLorCHARGE_CANCEL_REQ	*)pReq;
	int		nBodyLen = 0, nEnco = 0, nLen = 0;
	char	szOut[128], szGlobalSerialNo[128];

    Log(LOG_I, "[%4d] Begin Encode SellChargeCancel --------------------------\n", nThr);

	nEnco += SetValue(pReq+nEnco, MSG.globalSerialNo, sizeof(pstReq->globalSerialNo));
	nEnco += SetValue(pReq+nEnco, MSG.barCode, sizeof(pstReq->barCode));
	nEnco += SetValue(pReq+nEnco, MSG.giftCardKind, sizeof(pstReq->giftCardKind));
	nEnco += SetValue(pReq+nEnco, MSG.exchangeCode, sizeof(pstReq->exchangeCode));
	nEnco += SetValue(pReq+nEnco, MSG.giftKindCode, sizeof(pstReq->giftKindCode));
	nEnco += SetValue(pReq+nEnco, MSG.cashierId, sizeof(pstReq->cashierId));
	nEnco += SetValue(pReq+nEnco, MSG.billNo, sizeof(pstReq->billNo));
	nEnco += SetValue(pReq+nEnco, MSG.saleCode, sizeof(pstReq->saleCode));
	nEnco += SetValue(pReq+nEnco, MSG.originalApprovalAmount, sizeof(pstReq->originalApprovalAmount));
	nEnco += SetValue(pReq+nEnco, "12345", sizeof(pstReq->trackII));
	nEnco += SetValue(pReq+nEnco, MSG.originalApprovalDate, sizeof(pstReq->originalApprovalDate));
	nEnco += SetValue(pReq+nEnco, MSG.originalApprovalNo, sizeof(pstReq->originalApprovalNo));
	nEnco += SetValue(pReq+nEnco, MSG.originalcrdApprovalNo, sizeof(pstReq->originalcrdApprovalNo));

    Log(LOG_I, "[%4d] globalSerialNo(%s)\n", nThr, szGlobalSerialNo);

    Log(LOG_I, "[%4d] End Encode SellChargeCancel BodyLen(%d) --------------------------\n", nThr, nEnco);

	return nEnco;
}
